package com.zhushu.projectscheduling;

import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.DecimalFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.Map;

public class HelloController {

    /**
     * 组件初始化时执行
     */
    @FXML
    private void initialize() throws Exception{


    }


    @FXML
    private Label msgLabel;
    public void setMsgLabelMsg(String msg ,int state){
        if(state == 0){
            msgLabel.setTextFill(Color.RED);
        }else{
            msgLabel.setTextFill(Color.GREEN);
        }
        msgLabel.setFont(new Font(20));
        msgLabel.setText(msg);
    }

    @FXML
    private TextField sheetName;
    @FXML
    private TextField start_row;
    @FXML
    private TextField days_col;
    @FXML
    private TextField user_col;
    @FXML
    private TextField start_col;
    @FXML
    private TextField end_col;




    @FXML
    private Label fileAddr;


    @FXML
    private TextArea workdayTextArea;
    public void setWorkdayTextArea(String str){
        workdayTextArea.setText(str);
    }

    @FXML
    private TextArea holidayTextArea;
    public void setHolidayTextArea(String str){
        holidayTextArea.setText(str);
    }

    @FXML
    public TextArea consoleTextArea;

    /**
     * 页面弹出框
     * @param msg
     */
    private void alertMsg(String msg){
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setTitle("消息");
        alert.setHeaderText(msg);
        //alert.setContentText("请注意这是一个简单的弹出提示框示例。");
        alert.showAndWait();
    }

    @FXML
    private void selectExcel(){
        FileChooser fileChooser = new FileChooser();
        fileChooser.setTitle("选择Excel文件");
        Stage selectFile = new Stage();
        fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));
        fileChooser.getExtensionFilters().addAll(
                new FileChooser.ExtensionFilter("All Excel", "*.xlsx"),
                new FileChooser.ExtensionFilter("XLS", "*.xls"),
                new FileChooser.ExtensionFilter("XLSX", "*.xlsx"));
        File file = fileChooser.showOpenDialog(selectFile);
        if (file != null) {
            fileAddr.setText(file.getAbsolutePath());
        }
    }

    @FXML
    private void createScheduling(){
        String filePath = fileAddr.getText();
        if (!filePath.isEmpty()) {
            File file = new File(filePath);
            // 在这里添加你的文件解析逻辑
            System.out.println("解析文件: " + file.getAbsolutePath());
            // ...
            try {
                // 工作日集合
                Map<String, Integer> workdayMap = new HashMap<>();
                // 节假日集合
                Map<String, Integer> holidayMap = new HashMap<>();

                // 获取工作日
                String workdays = workdayTextArea.getText();
                String[] wArr = workdays.split("\n");
                for(String workday : wArr){
                    if(StringUtils.isNotBlank(workday)){
                        workdayMap.put(workday, null);
                    }
                }
                // 获取节假日
                String holidays = holidayTextArea.getText();
                String[] hArr = holidays.split("\n");
                for(String holiday : hArr){
                    if(StringUtils.isNotBlank(holiday)){
                        holidayMap.put(holiday, null);
                    }
                }

                doCreateScheduling(file, workdayMap, holidayMap);
                alertMsg("处理成功");
            } catch (Exception e) {
                e.printStackTrace();
                alertMsg("处理失败："+e.getMessage());
            }
        } else {
            alertMsg("请先选择一个文件！");
        }
    }


    private void doCreateScheduling(File file, Map<String, Integer> workdayMap, Map<String, Integer> holidayMap){

        // 获取原文件全路径
        String fileName_old = file.getAbsolutePath();
        // 找到最后一个点的位置
        int lastIndex = fileName_old.lastIndexOf('.');
        // 在最后一个点之前添加"_do"
        String fileName_new = fileName_old.substring(0, lastIndex) + "_ps" + fileName_old.substring(lastIndex);

        try {
            // 复制一个新文件
            Path sorucePath = Paths.get(fileName_old);
            Path destinPath = Paths.get(fileName_new);
            Files.copy(sorucePath, destinPath);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("复制文件出错"+e.toString());
        }

        File newFile = new File(fileName_new);

        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(newFile);
        } catch (FileNotFoundException e) {
            newFile.delete();
            e.printStackTrace();
            throw new RuntimeException("读取文件流出错"+e.getMessage());
        }

        // 获取该excel文件转换为Workbook
        Workbook workbook = null;
        try {
            // 获取文件名后缀
            String suffix = fileName_new.substring(fileName_new.lastIndexOf("."));
            if(suffix.equalsIgnoreCase(".xls")){
                workbook = new HSSFWorkbook(fileInputStream);
            }else{
                workbook = new XSSFWorkbook(fileInputStream);
            }

            //workbook = WorkbookFactory.create(newFile);       // 不知道为何用这种方式调试运行正常   打包后运行就报错
        } catch (Exception e) {
            newFile.delete();
            e.printStackTrace();
            throw new RuntimeException("读取Excel文件出错");

        }

        Sheet sheet = workbook.getSheet(sheetName.getText());

        Map<String, LocalDate> userDateMap = new HashMap<>();

        int cell_index_days = getColumnIndexForName(days_col.getText());
        int cell_index_user = getColumnIndexForName(user_col.getText());
        int cell_index_start = getColumnIndexForName(start_col.getText());
        int cell_index_end = getColumnIndexForName(end_col.getText());

        // 开始解析excel
        for(int i = Integer.valueOf(start_row.getText()) - 1; i <= sheet.getLastRowNum(); i++){
            Row row = sheet.getRow(i);
            // 工期
            Integer days = null;
            try {
                days = getNumberCellValue(row.getCell(cell_index_days)).intValue();
            } catch (Exception e) {
                newFile.delete();
                e.printStackTrace();
                throw new RuntimeException("工期只能为整数"+e.getMessage());
            }
            // 资源
            String user = getStringCellValue(row.getCell(cell_index_user));
            // 开始日期
            LocalDate startDate = getDateCellValue(row.getCell(cell_index_start));

            if(days ==null || StringUtils.isBlank(user)){
                continue;
            }else{
                if(startDate == null){
                    startDate = userDateMap.get(user);
                    Cell cell_startDate = row.getCell(cell_index_start);
                    if(cell_startDate == null){
                        cell_startDate = row.createCell(cell_index_start);
                    }
                    cell_startDate.setCellValue(startDate);
                }

                // 此处需要注意   假设开始时间是2020-01-01  工期为1天  那么结束时间也应该是2020-01-01  然后下一个开始日期加1天  为2020-01-02
                LocalDate endDate = addDate(startDate, days-1, workdayMap, holidayMap);
                Cell cell_endDate = row.getCell(cell_index_end);
                if(cell_endDate == null){
                    cell_endDate = row.createCell(cell_index_end);
                }
                cell_endDate.setCellValue(endDate);

                LocalDate nextStartDate = addDate(endDate, 1, workdayMap, holidayMap);
                userDateMap.put(user, nextStartDate);
            }

        }

        // 将修改后的Workbook写回到文件
        try {

            fileInputStream.close();

            FileOutputStream outputStream = new FileOutputStream(newFile);
            workbook.write(outputStream);

            workbook.close();
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            newFile.delete();
            e.printStackTrace();
            throw new RuntimeException("写入文件出错"+e.getMessage());
        }

    }

    /**
     * 根据EXCEL的列名获取其列索引值   如将B转化为1
     * @param columnName
     * @return
     */
    private static int getColumnIndexForName(String columnName){
        // 先将列名变为大写
        columnName = columnName.trim().toUpperCase();
        int columnIndex = 0;
        for (int i = 0; i < columnName.length(); i++) {
            char c = columnName.charAt(i);
            columnIndex = columnIndex * 26 + (c - 'A' + 1); // 加上1是因为Excel列是从1开始的
        }
        return columnIndex - 1; // 因为我们需要基于0的索引，所以最后减去1
    }

    /**
     * 获取单元格利的字符串
     * @param cell
     * @return
     */
    private static String getStringCellValue(Cell cell){
        if(null == cell){
            return null;
        }else{
            if(cell.getCellType() == CellType.NUMERIC){
                return new DecimalFormat("#.########").format(cell.getNumericCellValue());
            }else if(cell.getCellType() == CellType.ERROR){
                return null;
            }
        }
        return cell.getRichStringCellValue().getString().trim();
    }

    /**
     * 获取单元格里的数字
     * @param cell
     * @return
     */
    private static Double getNumberCellValue(Cell cell){
        if(null == cell || cell.getCellType()== CellType.BLANK){
            return null;
        }else if(cell.getCellType() == CellType.NUMERIC){
            return cell.getNumericCellValue();
        }else{
            return parseNumberD(cell.getRichStringCellValue().getString().trim());
        }
    }

    /**
     * 获取单元格里的日期
     * @param cell
     * @return
     */
    public static LocalDate getDateCellValue(Cell cell){
        if(null == cell)
            return null;
        return cell.getLocalDateTimeCellValue().toLocalDate();
    }

    public static Double parseNumberD(String text) {
        if (StringUtils.isBlank(text)) {
            return null;
        } else {
            return Double.valueOf(text.trim().replaceAll(",", ""));
        }
    }

    private static LocalDate addDate(LocalDate startDate, int num, Map<String, Integer> workdayMap, Map<String, Integer> holidayMap){
        LocalDate currentDate = startDate;
        int count = 0; // 用于计数已经找到的工作日数量

        while (count < num) {
            currentDate = currentDate.plusDays(1); // 移动到下一天
            String currentDateStr = currentDate.toString();

            // 检查是否是默认休息日但workdayMap中有标记为工作日
            if (isWeekend(currentDate) && workdayMap.containsKey(currentDateStr)) {
                // 是特殊工作日，计入工作日计数
                count++;
            }
            // 检查是否是工作日但holidayMap中有标记为调休日
            else if (!isWeekend(currentDate) && holidayMap.containsKey(currentDateStr)) {
                // 是调休日，不计入工作日计数
            }
            // 如果既不是周末也不是调休日，则为工作日，计入工作日计数
            else if (!isWeekend(currentDate) && !holidayMap.containsKey(currentDateStr)) {
                count++;
            }
            // 无需对周末且不在workdayMap中的情况做特别处理，因为它自然不计入工作日
        }

        return currentDate;
    }
    private static boolean isWeekend(LocalDate date) {
        return date.getDayOfWeek() == DayOfWeek.SATURDAY || date.getDayOfWeek() == DayOfWeek.SUNDAY;
    }

}